﻿#include "OperSolve.h"
#include "OperCSVPostDataImport.h"
#include "GUIDialog/GUIPostDialog/GUISolverDialog.h"
#include "FITK_Kernel/FITKAppFramework/FITKProgramTaskManager.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppSettings.h" 
#include "FITK_Kernel/FITKAppFramework/FITKComponents.h"

#include "FITK_Kernel/FITKCore/FITKThreadPool.h"
#include "FITK_Component/FITKVAOneXMLIO/FITKVAOneXMLIOInterface.h"
#include "FITK_Component/FITKVAOneHDF5IO/FITKVAOneHDF5IOInterface.h"
#include "FITK_Component/FITKAcousticsPostData/FITKAcousticsPostData.h"

#include "GUIFrame/MainWindow.h"

#include <QFileInfo>
#include <QCoreApplication>

namespace GUIOper
{
    bool OperSolve::execGUI()
    {
        //打开求解窗口
        GUI::MainWindow * mainWindow = dynamic_cast<GUI::MainWindow *>(FITKAPP->getGlobalData()->getMainWindow());
        if (!mainWindow)return false;
        GUI::GUISolverDialog* dialog = new GUI::GUISolverDialog(this, mainWindow);
        connect(dialog, &QDialog::accepted, this, &OperSolve::execProfession);
        dialog->show();
        return false;
    }

    bool OperSolve::execProfession()
    {
        QString solveFileName;
        if (!this->argValue<QString>("SolverFile", solveFileName)) return false;
        //读写组件获取
        VAOne::FITKVAOneXMLIOInterface* xmlIO = FITKAPP->getComponents()->
            getComponentTByName<VAOne::FITKVAOneXMLIOInterface>("VAOneXMLIO");

        //等待线程结束
        Core::FITKThreadPool::getInstance()->wait();

        if (xmlIO == nullptr) return false;
        //清理信号关联
        QObject::disconnect(xmlIO, SIGNAL(ioThreadFinishedSig()), nullptr, nullptr);
        //获取要存储的数据位置
        Core::FITKAbstractDataObject* model =
            FITKAPP->getGlobalData()->getMeshData<Core::FITKAbstractDataObject>();
        Core::FITKAbstractDataObject* physics =
            FITKAPP->getGlobalData()->getPhysicsData<Core::FITKAbstractDataObject>();
        //传入参数
        xmlIO->setDataObject("Model", model);
        xmlIO->setDataObject("Physics", physics);
        xmlIO->setFileName(solveFileName);
        xmlIO->runInThread();
        //关联结束导出槽函数
        connect(xmlIO, &VAOne::FITKVAOneXMLIOInterface::ioThreadFinishedSig, this, &OperSolve::solverOper, Qt::UniqueConnection);
        //执行导出
        xmlIO->exec(2);

        
        return true;
    }

    void OperSolve::solverOper()
    {
        QString solveFileName;
        QString resultFileName;
        QString solverType;
        QString workDir;
        if (!this->argValue<QString>("SolverFile", solveFileName)) return;
        if (!this->argValue<QString>("ResultFileFile", resultFileName)) return;
        if (!this->argValue<QString>("SolverType", solverType)) return;
        if (!this->argValue<QString>("WorkDir", workDir)) return;
        // 获取第三方程序驱动输入信息
        SEASolverInfo* inputInfo = new SEASolverInfo;
        inputInfo->setNeedSolveFile(solveFileName);
        inputInfo->setResultFile(resultFileName);
        inputInfo->setSolverType(solverType);
        AppFrame::FITKProgramTaskManeger* programTaskMgr = FITKAPP->getProgramTaskManager();
        if (!programTaskMgr) return;
        AppFrame::FITKExecProgramDriver* driverProgramer = dynamic_cast<AppFrame::FITKExecProgramDriver*>(programTaskMgr->createProgram(2, "SEASolver", inputInfo));
        if (!driverProgramer) return;
        connect(driverProgramer, &AppFrame::FITKAbstractProgramerDriver::sig_Finish, this, &OperSolve::importResult, Qt::UniqueConnection);
        driverProgramer->setWorkingDirectory(workDir);
        driverProgramer->start();
    }

    void OperSolve::importResult()
    {
        QString solverType;
        if (!this->argValue<QString>("SolverType", solverType)) return;
        //清除后处理数据
        this->clearPostData();
        QString resultFileName, csvFileName;
        if (solverType.isEmpty())
        {
            if (!this->argValue<QString>("ResultFileFile", resultFileName) || !this->argValue<QString>("CSVFileFile", csvFileName)) return;
            this->importResultHDF5(resultFileName);
            this->importResultCSV(csvFileName);
        }
        else if (solverType == "-param")
        {
            if (!this->argValue<QString>("CSVFileFile", csvFileName)) return;
            this->importResultCSV(csvFileName);
        }
    }

    void OperSolve::importResultHDF5(QString file)
    {
        if (file.isEmpty()) return;
        //读写组件获取
        VAOne::FITKVAOneHDF5IOInterface* hdf5IO = FITKAPP->getComponents()->
            getComponentTByName<VAOne::FITKVAOneHDF5IOInterface>("VAOneHDF5IO");

        //等待线程结束
        Core::FITKThreadPool::getInstance()->wait();

        if (nullptr == hdf5IO) return;

        //获取要存储的数据位置
        Core::FITKAbstractDataObject* postData =
            FITKAPP->getGlobalData()->getPostData<Core::FITKAbstractDataObject>();

        hdf5IO->setDataObject("postData", postData);
        hdf5IO->setFileName(file);
        hdf5IO->runInThread();
        //关联结束读取槽函数
        connect(hdf5IO, SIGNAL(ioThreadFinishedSig()), this, SLOT(ioHDF5IOThreadFinishedSlot()), Qt::UniqueConnection);
        //执行读取
        hdf5IO->exec(1);
    }

    void OperSolve::importResultCSV(QString file)
    {
        if (file.isEmpty()) return;
        ModelOper::ImportCSVFileThread* thread = new ModelOper::ImportCSVFileThread(this);
        thread->setFileName(file);
        //获取线程池
        Core::FITKThreadPool* pool = Core::FITKThreadPool::getInstance();
        if (pool == nullptr)return;
        //等待线程结束
        pool->wait();
        pool->execTask(thread);
    }

    void OperSolve::clearPostData()
    {
        Acoustics::FITKAcousticsPostData* postData =
            FITKAPP->getGlobalData()->getPostData<Acoustics::FITKAcousticsPostData>();

        if (postData) postData->clearData();
    }

    void OperSolve::ioHDF5IOThreadFinishedSlot()
    {
        VAOne::FITKVAOneHDF5IOInterface* hdf5IO = FITKAPP->getComponents()->
            getComponentTByName<VAOne::FITKVAOneHDF5IOInterface>("VAOneHDF5IO");
        if (hdf5IO == nullptr) return;
        //取消关联
        disconnect(hdf5IO, SIGNAL(ioThreadFinishedSig()), this, SLOT(ioHDF5IOThreadFinishedSlot()));
    }

    SEADriver::SEADriver()
    {
        //获取求解器路径
        QString solverPath = QCoreApplication::applicationDirPath() + QString("/../Solver/sea_c.exe");
        this->setExecProgram(QFileInfo(solverPath).absoluteFilePath());
    }

    SEADriver::~SEADriver()
    {

    }

    bool SEADriver::isExistSolver()
    {
        return QFileInfo(this->getExecProgram()).isFile();
    }

    int SEADriver::getProgramType()
    {
        return 2;
    }

    QString SEADriver::getProgramName()
    {
        return "SEASolver";
    }

    SEASolverInfo::~SEASolverInfo()
    {

    }

    void SEASolverInfo::setNeedSolveFile(QString needSolerFile)
    {
        _needSolverFile = needSolerFile;
    }

    void SEASolverInfo::setResultFile(QString resultFile)
    {
        _resultFile = resultFile;
    }

    void SEASolverInfo::setSolverType(QString type)
    {
        _solverType = type;
    }

    QStringList SEASolverInfo::args()
    {
        QStringList info;
        info << "-f" << _needSolverFile << _resultFile;
        if (!_solverType.isEmpty())
            info << _solverType;
        return info;
    }

}
